package com.cctc.juc.source.Athread.threadpool;

import java.util.HashSet;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * [ThreadPoolExecutor 线程池] （核心）实现类。
 * 要求：熟练、流畅的表述 ThreadPoolExecutor 线程池的全栈知识点，包括：
 * - 概述；
 * - 核心逻辑实现原理；
 * - 使用方式，参数配置，生命周期，优雅终止等；
 * - 总结。
 * ThreadPoolExecutor 线程池核心逻辑内部实现原理（熟练表述）：
 * ThreadPoolExecutor 线程池的核心逻辑就是工作线程不断从任务队列中获取任务去执行，其中工作线程 Worker 是线程池中的一个内部类，该类继承自 AQS，并实现了 Runnbale 接口，且内部依赖于一个任务执行器线程实例，实现了 “自旋” 式的从任务队列中获取任务并以线程安全的方式互斥执行。
 * 1）当用户向线程池中提交一个任务时，线程池会根据其配置参数以及当前池中（核心 & 非核心）工作线程的数量进行动态伸缩，例如当（核心）工作线程数量 count < corePoolSize
 * 时，会新建一个（核心）工作线程，将其放入到线程池中，执行新提交的任务；否则，就会将新提交的任务加入到（有界）任务队列中进行排队；当（有界）任务队列满时，线程池又会再次创建一个（非核心）工作线程，将其放入到线程池中，执行新提交的任务；当（核心 & 非核心）工作线程数量 > maximumPoolSize 时，新提交的任务将会被线程池采用配置好的策略进行拒绝；此外，被加入到线程池中的工作线程会启动 “自旋” 执行任务流程，不断地从任务队列中获取任务，然后以线程安全的方式互斥执行；当线程池不繁忙时，（非核心）线程空闲时间一旦超过 keepAliveTime，就会被线程池所回收，以节省资源；最终，线程池中工作线程的数量会逐渐趋于 corePoolSize，达到相对平衡状态。
 * 2）当线程池中的任务队列不为空但无任何工作线程可用，或者任务队列为空且所有任何工作线程都被终止时，或者用户显式调用了 shutdown()、shutdownNow()、terminate() 方法，线程池都将会进行终止状态。
 * 总而言之，ThreadPoolExecutor 线程池通过非常优秀的设计，可以实现动态调整工作线程的数量，合理复用线程资源，去处理用户提交的任务，以达到理想的效果。
 */
public class DThreadPoolExecutor_AAAAA extends AbstractExecutorService {
    /**
     * [Worker] 线程池中的工作线程。
     * 描述信息：该类继承自 AQS（抽象队列同步器）[（互斥）锁]，同时实现了 Runnable 接口并依赖于 Thread 类，使用自己（this）的线程执行自身的异步任务，合二为一，即为 【自带（互斥）锁的工作线程】。
     * 说明：该类作为线程池中的（工作）线程，所实现的 AQS（抽象队列同步器）[（互斥）锁] 主要用于控制（工作）线程是否可以被中断？
     * 1）构造器中将同步状态 state 设置为 -1，表示为初始状态，还未运行 runWorker() 方法，禁止中断；
     * 2）调用 run() 方法，执行 runWorker(this) 方法 [使用自己（this）的线程执行自身的异步任务]，将同步状态 state 设置为 0，表示已启动，可以中断。
     * 当线程池的 shutdownNow() 方法被调用时，所有 state >= 0 [已经执行了 runWorker() 方法] 的 Worker 工作线程都会被中断。
     */
    private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;

        public Worker(Runnable firstTask) {
            /**
             * [核心代码]
             * AQS 代码，将同步状态设置为 -1（加锁，然后由 runWork() 方法将其更新为 0 进行解锁），防止 runWorker() 方法在运行之前被中断。
             * - 因为当 shutdownNow() 方法被调用时，线程池中所有 state >= 0 [已经执行了 runWorker() 方法] 的 Worker 工作线程都会被中断。
             */
            setState(-1);
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

        @Override
        public void run() {
            /**
             * [核心代码]
             * 首先调用 unlock() 方法将 Worker 工作线程的同步状态更新为 0，进行解锁，标识当前 Worker 工作线程已经执行了 runWorker() 方法。
             * - 当线程池的 shutdownNow() 方法被调用时，所有 state >= 0 [已经执行了 runWorker() 方法] 的 Worker 工作线程都会被中断。
             */
            runWorker(this);
        }

        /**
         * 中断 Worker 工作线程。
         * - 当同步状态 >= 0 [已启动，已运行 runWorker() 方法] && Worker 工作线程存在且未被中断时，中断 Worker 工作线程
         */
        void interruptIfStarted() {
            Thread t;
            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
                try {
                    t.interrupt();
                } catch (SecurityException ignore) {
                }
            }
        }

        /**
         * AQS（抽象队列同步器）实现代码：
         * - protected boolean tryAcquire(int unused)，尝试获取同步资源（state）；
         * - protected boolean tryRelease(int unused)，尝试释放同步资源（state）；
         * - protected boolean isHeldExclusively，是否持有同步资源（state）？
         */

        protected boolean isHeldExclusively() {
            /**
             * -1：初始化，未启动（禁止中断）状态；
             * 0：已启动，未加锁（已运行 runWork() 方法，state >= 0，可以中断）状态；
             * 1：加锁状态。
             */
            return getState() != 0;
        }

        protected boolean tryAcquire(int unused) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        protected boolean tryRelease(int unused) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        /**
         * （互斥）锁实现代码：
         * - public void lock()，加（互斥）锁；
         * - public boolean tryLock()，尝试加（互斥）锁；
         * - public void unlock()，解（互斥）锁；
         * - public boolean isLocked()，是否持有（互斥）锁。
         */

        public void lock() {
            acquire(1);
        }

        public boolean tryLock() {
            return tryAcquire(1);
        }

        public void unlock() {
            release(1);
        }

        public boolean isLocked() {
            return isHeldExclusively();
        }

    }

    // --- [核心] 属性 --- //

    /**
     * [高 3 位（线程池运行状态）] + [低 29 位（Worker 工作线程数量）]
     * 1. [线程池生命周期] 线程池运行状态变化过程。
     * 2. [池线程任务调度] 线程池任务调度流程，即 Worker 工作线程数量变化过程。
     */
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    /**
     * 1. [线程池生命周期] 线程池运行状态变化过程。
     * RUNNING（-1） -> SHUTDOWN（0） -> STOP（1） -> TIDYING（2） -> TERMINATED（3）。
     * - RUNNING（-1）：运行状态，线程池创建之后的初始状态，能接收新任务，也能处理阻塞队列中排队的任务；
     * - SHUTDOWN（[核心] 0）：（有序）关闭状态，调用 shutdown() 之后的状态，不能接收新任务，但能处理工作队列中的任务；
     * - STOP（[核心] 1）：（立即）停止状态，调用 shutdownNow() 之后的状态，不能接收新任务，也不能处理工作队列中的任务，并且会中断所有的 Worker 工作线程，然后返回工作队列中尚未执行的任务；
     * - TIDYING（2）：休整状态，等到工作队列为空，所有 Worker 工作线程都已经终止时，线程池就会进入该状态，然后执行 terminated() 钩子方法；
     * - TERMINATED（3）：终止状态，调用 terminated()、awaitTerminated() 之后的状态，线程池已终止。
     * 总结：从以上的状态定义不难看出，线程池生命周期的核心在于如何优雅地关闭线程池，同时也是面试的重点之一。
     * {优雅的关闭线程池}，主要涉及 3 个方法：
     * - shutdown()，有序关闭线程池，此方法会将线程池状态更新为 SHUTDOWN，此状态下的线程池：
     * 1）不再接收新任务，如果还继续往线程池中提交新任务，将会使用线程池的拒绝策略进行响应，默认的拒绝策略为 AbortPolicy（直接拒绝），直接抛出 RejectedExecutionException 拒绝执行异常，其他可选拒绝策略包括 DiscardPolicy（直接丢弃）、DiscardOldestPolicy（丢弃最老的）、CallerRunsPolicy（调用者执行）、自定义拒绝策略等；
     * 2）等待工作队列中的任务全部有序执行完毕后，进入 STOP 状态。
     * - shuwdownNow()，立即停止线程池，此方法会立即将线程池更新为 STOP，此状态下的线程池：
     * 1）不再接收新任务，同上；
     * 2）清空工作队列中的任务，返回给调用者；
     * 3）中断所有的 Worker 工作线程，当所有 Worker 工作线程都已经终止时，进入 TIDYING 状态。
     * --> 中断不代表立即终止，只是设置了中断标识，需要用户程序主动配合线程进行中断操作。
     * - awaitTerminated()，（限时）等待线程池终止，如果在等待时间内线程池完成终止，则返回 true，否则返回 false。
     * 结合使用 shutdown()、shutdownNow()、awaitTerminated() 方法，实现 {优雅的关闭线程池} 的大致过程如下：
     * 1）调用 shutdown() 方法，拒绝新任务，并等待所有工作队列中的任务全部有序执行完毕；
     * 2）调用 awaitTerminated() 方法，限时等待，判断线程池是否已终止；
     * 3）如果 awaitTerminated() 方法返回 false 或被中断，就调用 shutdownNow() 方法，立即清空工作队列中的任务，中断所有的 Worker 工作线程；
     * 4）再次调用 awaitTerminated() 方法，限时等待，判断线程池是否已终止；
     * 5）重复执行 3）和 4），不断关闭线程池，直到线程池终止。
     * 说明：我们可以在 JVM 中注册一个钩子函数或信号，在 JVM 进程关闭之前，由钩子函数或信号自动执行上边 {优雅关闭线程池} 的代码，以确保系统资源正常释放。
     */
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int RUNNING = -1 << COUNT_BITS;
    private static final int SHUTDOWN = 0 << COUNT_BITS;
    private static final int STOP = 1 << COUNT_BITS;
    private static final int TIDYING = 2 << COUNT_BITS;
    private static final int TERMINATED = 3 << COUNT_BITS;

    /**
     * 2. [池线程任务调度] 线程池任务调度流程，即 Worker 工作线程数量变化过程。
     * - corePoolSize，（核心）线程数量；
     * - workQueue，工作队列；
     * - maximumPoolSize，（最大）线程数量；
     * 线程池将根据 corePoolSize、workQueue 和 maximumPoolSize 值自动维护池化线程的数量 count，大致规则如下：
     * 1）如果 count < corePoolSize，即使其他 Worker 工作线程处于空闲状态，线程池也会创建一个新的（核心）线程处理新任务，直到达到 corePoolSize；
     * 2）如果已经达到 corePoolSize，且 count < maximumPoolSize，线程池不会直接创建新线程，而是将其放入到 workQueue 工作队列中进行排队；
     * 3）如果 workQueue（有界）工作队列已满，且 count < maximumPoolSize，线程池将会创建一个新的（非核心）线程处理新任务，直到达到 maximumPoolSize；
     * 4）如果已经达到 maximumPoolSize 或已关闭，线程池将使用拒绝策略进行响应，默认的拒绝策略为 AbortPolicy（直接拒绝），直接抛出 RejectedExecutionException 拒绝执行异常，其他可选拒绝策略包括 DiscardPolicy（直接丢弃）、DiscardOldestPolicy（丢弃最老的）、CallerRunsPolicy（调用者执行）、自定义拒绝策略等。
     * 5）如果（非）核心线程或核心线程设置了 allowCoreThreadTimeout = true，当其空闲时间超过了 keepAliveTime，将会被回收。
     * 说明：
     * - 如果设置 corePoolSize = maximumPoolSize，则可以创建一个固定大小的线程池。
     * - 如果选用的 workQueue 工作队列为（无界）阻塞队列或直接设置 maximumPoolSize = Integer.MAX_VALUE，则可以创建一个无限容量的线程池，该线程池可以接收任意数量的并发任务。
     * 注意：如果线程池中的线程数量配置不合理，反而适得其反，降低应用的性能。
     * 1）对于 CPU （计算）密集型任务，一般设置为 {CPU 核心数 + 1}；
     * 2）对于 I/O （本地存取、网络传输）密集型任务，一般设置为 {CPU 核心数 * 2]}；
     * 3）对于混合型任务，业界有一个比较成熟的估算公式为 {CPU 核心数 * （CPU 计算时间 + I/O 等待时间）}。
     */
    private volatile int corePoolSize;
    private volatile int maximumPoolSize;
    private volatile long keepAliveTime;
    private volatile boolean allowCoreThreadTimeout;
    // 创建 Worker 工作线程的工厂
    private volatile ThreadFactory threadFactory;
    // 存放 Worker 工作线程的集合，访问这个集合，必须获得 mainLock 锁
    private final HashSet<Worker> workers = new HashSet<>();
    // 主锁：可重入（互斥）锁
    private final ReentrantLock mainLock = new ReentrantLock();
    // 在主锁中（阻塞）等待的条件队列
    private final Condition termination = mainLock.newCondition();
    // 存放新任务的（阻塞）工作队列，整个线程池实现的基本思想就是从 workQueue 中不断取出需要执行的任务，放在 Workers 工作线程中进行处理。
    private final BlockingQueue<Runnable> workQueue;
    // 已完成的任务数量
    private long completedTaskCount;
    // 拒绝策略
    private volatile RejectedExecutionHandler handler;
    // 默认拒绝策略
    private static final RejectedExecutionHandler defaultHandler = new ThreadPoolExecutor.AbortPolicy();

    /**
     * [核心] 构造器
     *
     * @param corePoolSize    核心线程数
     * @param maximumPoolSize 最大线程数
     * @param keepAliveTime   （非）核心线程或核心线程设置了 allowCoreThreadTimeout = true 时，空闲线程存活时间
     * @param unit            空闲线程存活时间单位
     * @param workQueue       （阻塞）工作队列
     * @param threadFactory   创建 Worker 工作线程的工厂，默认为 Executors.DefaultThreadFactory；
     * @param handler         新任务拒绝策略，默认为 AbortPolicy（直接拒绝，并抛出异常）
     */
    public DThreadPoolExecutor_AAAAA(int corePoolSize, int maximumPoolSize,
                                     long keepAliveTime, TimeUnit unit,
                                     BlockingQueue<Runnable> workQueue,
                                     ThreadFactory threadFactory,
                                     RejectedExecutionHandler handler) {
        // ... 省略代码 ...
    }

    // --- [钩子] 函数 --- //

    protected void beforeExecute(Thread t, Runnable r) {
        /**
         * 前钩子：每个任务执行之前的钩子函数。
         * 此方法由 Worker 工作线程在执行每个任务之前调用，可用于：
         * - 重新初始化 ThreadLocal 线程本地变量实例；
         * - 更新日志记录；
         * - 开始计时统计；
         * - 更新上下文变量等。
         */
    }

    protected void afterExecute(Runnable r, Throwable t) {
        /**
         * 后钩子：每个任务执行之后的钩子函数。
         * 此方法由 Worker 工作线程在执行每个任务之后调用，可用于：
         * - 清除 ThreadLocal 线程本地变量；
         * - 更新日志记录；
         * - 收集统计信息；
         * - 更新上下文变量等。
         */
    }

    protected void terminated() {
        /**
         * 终止钩子：线程池终止时的钩子函数。
         * 此方法由线程池在其终止时 [tryTerminate() 方法内] 调用，可用于：
         * - 关闭、清除、回收资源等。
         */
    }

    void onShutdown() {
        /**
         * （有序）关闭线程池钩子：线程池（有序）关闭时的钩子函数。
         * 此方法由线程池在其（有序）关闭时 [shutdown() 方法内] 调用，交由子类重写，可用于：
         * - 关闭、清除、回收资源等。
         */
    }

    // --- [核心] 方法 --- //

    /**
     * 向线程池中提交一个任务。
     * 1）如果当前线程池中的（核心）工作线程数量 count < corePoolSize，则新建一个（核心）工作线程，并将其加入到线程池中执行任务；
     * 2）否则，将新提交的任务放入任务队列；
     * 3）如果任务队列已满，则再新建一个（非核心）工作线程，并将其加入到线程池中执行任务；
     * 4）如果当前线程池中的（核心 & 非核心）工作线程数量 count > maximumPoolSize，则拒绝新提交的任务；
     * 此外，当一个 Worker 工作线程执行完当前任务后，它会自动从任务队列中取下一个任务来执行。
     * 当一个 Worker（非核心）工作线程无事可做，超过一定的时间（keepAliveTime）时，线程池会进行判断：
     * - 如果当前运行的 Worker 工作线程数大于 corePoolSize ，那么这个 Worker（非核心）工作线程就被终止。
     * 所以，当线程池不繁忙时，Worker 工作线程的数量最终会收缩到 corePoolSize 的大小。
     * 最后，如果线程池的任务队列非空但没有可用的 Worker 工作线程，或者任务队列为空且所有 Worker 工作线程都已回收（corePoolSize = 0 || allowCoreThreadTimeOut = true），线程池将会被终止。
     */
    @Override
    public void execute(Runnable task) {
        /**
         * 面试题：线程池中的线程是怎么创建的？是一开始就随着线程池的启动创建好的吗？
         * ThreadPoolExecutor 作为 Java 线程池中最核心的（实现）类之一，它能够保证线程池按照正常的业务逻辑执行任务，并通过 CAS 原子的方式更新线程池每个阶段的状态。
         * - ThreadPoolExecutor 类中存在一个 workers 工作线程集合，线程池默认初始化后不启动 Worker 工作线程，等待有请求任务时才创建并启动 Worker 工作线程，用户可以向线程池中提交需要执行的任务，workers 集合中的工作线程可以直接执行任务，或者从任务队列中获取任务后执行。
         * - ThreadPoolExecutor 类提供了整个线程池从创建到执行任务，再到终止的整个流程方法，主要包括 execute()、addWorker()、addWorkerFailed()、shutdown()、shutdownNow()、awaitTerminated() 等方法。
         * 这里，我们结合 execute() 方法，理解一下 ThreadPoolExecutor 线程池的执行逻辑：
         * 1）如果线程数量 count < corePoolSize，则向线程池中添加一个（核心）线程，执行新提交的任务；
         * 2）否则，将任务添加到任务队列；
         * 3）如果（有界）任务队列 workQueue 已满，则向线程池中添加一个（非核心）线程，执行新提交的任务；
         * 4）如果线程数量 count >= maximumPoolSize，则执行拒绝策略。
         * 最后，当一个 Worker 工作线程执行完当前任务后，它会从任务队列中取下一个任务来执行。当一个 Worker 工作线程无事可做，超过一定的时间（keepAliveTime）时，线程池会进行判断：
         * - 如果当前运行的线程数大于 corePoolSize ，那么这个线程就被终止。
         * 所以线程池的所有任务完成后，它最终会收缩到 corePoolSize 的大小。
         */
        // 如果提交任务为空，则直接抛出空指针异常
        if (task == null) throw new NullPointerException();
        // 获取线程池的状态 state 和线程数量 count
        int c = ctl.get();
        // 1）如果线程数量 count < corePoolSize
        if (workerCountOf(c) < corePoolSize) {
            // 向线程池中添加一个（核心）线程执行新提交的任务
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 2）如果线程池的状态 state == RUNNING，则将任务添加到任务队列
        if (isRunning(c) && workQueue.offer(command)) {
            // 重新检查线程池的状态 state 和线程数量 count
            int recheck = ctl.get();
            // 如果线程池的状态 state != RUNNING，则将新提交的任务从任务队列中移除出去
            if (!isRunning(recheck) && remove(command)) {
                // 执行拒绝策略
                reject(command);
            }
            // 如果线程数量 count == 0，则向线程池中添加一个（非核心）线程
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 3）如果（有界）任务队列 workQueue 已满，则向线程池中添加一个线程，执行新提交的任务
        else if (!addWorker(command, false))
            // 4）如果线程数量 count >= maximumPoolSize，则执行拒绝策略
            reject(command);
    }

    /**
     * 向线程池中添加一个工作线程，并启动它的任务执行器，执行目标任务。
     * 1）根据新提交的任务创建一个工作线程；
     * 2）将工作线程以线程安全的方式加入到线程池中；
     * 3）启动工作线程的任务执行器，执行目标任务。
     */
    private boolean addWorker(Runnable firstTask, boolean core) {
        boolean workerAdded = false, workerStarted = false;
        Worker worker = null;
        try {
            //  1）根据新提交的任务创建一个工作线程；
            worker = new Worker(firstTask);
            final Thread executor = worker.executor;
            if (executor != null) {
                // 2）将工作线程以线程安全的方式加入到线程池中；
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    workers.add(worker);
                    workerAdded = true;
                } finally {
                    mainLock.unlock();
                }
                // 3）启动工作线程的任务执行器，执行目标任务。
                if (workerAdded) {
                    executor.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (!workerStarted) addWorkerFailed(worker);
        }
        return workerStarted;
    }

    private void addWorkerFailed(Worker w) {
        /**
         * 核心逻辑点：如果添加 Worker 工作线程失败，或 Worker 工作线程启动失败，需要调用此方法，执行删除逻辑。
         * - 获取独占锁，将 Worker 工作线程从 workers 中移除，并通过 CAS 将任务数量减 1，最后释放锁。
         */
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w);
            decrementWorkerCount();
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * 运行任务执行器，启动 “自旋” 执行任务流程。
     * 1）获取当前任务执行器；
     * 2）更新锁状态 -1 -> 0，标记当前工作线程完成初始化，且已启动，允许被中断；
     * 3）启动 “自旋” 执行任务流程：获取新提交的任务，或者不断从线程池的任务队列中获取任务，并以线程安全的方式互斥执行；
     * 3.1）加锁（0 -> 1）；
     * 3.2）主动检查是否需要中断任务执行器的 “自旋” 执行任务流程；
     * 3.3）调用 beforeExecute() 钩子函数，运行任务执行前的处理逻辑；
     * 3.4）调用 task.run()，执行目标任务；
     * 3.5）调用 afterExecute() 钩子函数，运行任务执行后的处理逻辑；
     * 3.6）解锁（1 -> 0），并累加任务完成数 + 1；
     * 4）工作线程终止前，累加线程池的总任务完成数，然后从线程池中移除工作线程。
     */
    final void runWorker(Worker worker) {
        // 1）获取当前任务执行器；
        Thread executor = Thread.currentThread();
        Runnable task = worker.firstTask;
        worker.firstTask = null;
        // 2）更新锁状态 -1 -> 0，标记当前工作线程完成初始化，且已启动，允许被中断；
        worker.unlock();
        try {
            //  3）启动 “自旋” 执行任务流程：获取新提交的任务，或者不断从线程池的任务队列中获取任务，并以线程安全的方式互斥执行；
            while (task != null || (task = getTask()) != null) {
                // 3.1）加锁（0 -> 1）；
                worker.lock();
                // 3.2）主动检查是否需要中断任务执行器的 “自旋” 执行任务流程；
                if (Thread.interrupted() && !executor.isInterrupted()) executor.interrupt();
                try {
                    // 3.3）调用 beforeExecute() 钩子函数，运行任务执行前的处理逻辑；
                    beforeExecute(executor, task);
                    Throwable thrown = null;
                    try {
                        // 3.4）调用 task.run() 方法，执行目标任务；
                        task.run();
                    } catch (Exception e) {
                        thrown = e;
                        throw e;
                    } finally {
                        // 3.5）调用 afterExecute() 钩子函数，运行任务执行后的处理逻辑；
                        afterExecute(task, thrown);
                    }
                } finally {
                    // 3.6）解锁（1 -> 0），并累加任务完成数 + 1；
                    task = null;
                    worker.completedTasks++;
                    worker.unlock();
                }
            }
        } finally {
            // 4）工作线程终止前，累加线程池的总任务完成数，然后从线程池中移除工作线程。
            processWorkerExit(worker);
        }
    }

    private Runnable getTask() {
        for (; ; ) {
            if (workQueue.isEmpty()) return null;
            try {
                Runnable task = workQueue.take();
                if (task != null) return task;
            } catch (InterruptedException retry) {
            }
        }
    }

    private void processWorkerExit(Worker worker) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            completedTaskCount += worker.completedTasks;
            workers.remove(worker);
        } finally {
            mainLock.unlock();
        }
    }

    @Override
    public Future<?> submit(Runnable task) {
        // 2. 提交新任务，无返回值，可以抛出异常信息，通过 Future 捕获异常。
        // ... 省略代码 ...
        return super.submit(task);
    }

    @Override
    public <T> Future<T> submit(Runnable task, T result) {
        // 3. 提交新任务，有（指定）返回值，可以抛出异常信息，通过 Future 获取结果及捕获异常。
        // ... 省略代码 ...
        return super.submit(task, result);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        // 4. 提交新任务，有（执行）返回值，可以抛出异常信息，通过 Future 获取结果及捕获异常。
        // ... 省略代码 ...
        return super.submit(task);
    }

    @Override
    public void shutdown() {
        /**
         * 有序关闭线程池，此方法会将线程池状态更新为 SHUTDOWN，此状态下的线程池：
         * 1）不再接收新任务，如果还继续往线程池中提交新任务，将会使用线程池的拒绝策略进行响应，默认的拒绝策略为 AbortPolicy（直接拒绝），直接抛出 RejectedExecutionException 拒绝执行异常，其他可选拒绝策略包括 DiscardPolicy（直接丢弃）、DiscardOldestPolicy（丢弃最老的）、CallerRunsPolicy（调用者执行）、自定义拒绝策略等；
         * 2）等待工作队列中的任务全部有序执行完毕后，进入 STOP 状态。
         */
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // 检查权限
            checkShutdownAccess();
            // 设置 SHUTDOWN 状态
            advanceRunState(SHUTDOWN);
            // [注意] 中断空闲线程
            interruptIdleWorkers();
            // 钩子函数，清理一些资源
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

    @Override
    public List<Runnable> shutdownNow() {
        /**
         * 立即停止线程池，此方法会立即将线程池更新为 STOP，此状态下的线程池：
         * 1）不再接收新任务，同上；
         * 2）清空工作队列中的任务，返回给调用者；
         * 3）中断所有的 Worker 工作线程，当所有 Worker 工作线程都已经终止时，进入 TIDYING 状态。
         */
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // 检查权限
            checkShutdownAccess();
            // 设置 STOP 状态
            advanceRunState(STOP);
            // [注意] 中断所有的 Worker 工作线程，包括空闲线程
            interruptWorkers();
            // 清空工作队列中的任务，返回给调用者
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
        return tasks;
    }

    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        /**
         * （限时）等待线程池终止。
         * - 如果在等待时间内线程池完成终止，则返回 true，否则返回 false。
         */
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (; ; ) {
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

    @Override
    public boolean isShutdown() {
        return !isRunning(ctl.get());
    }

    @Override
    public boolean isTerminated() {
        return runStateAtLeast(ctl.get(), TERMINATED);
    }

}
